﻿using System;
using System.Collections.Generic;
using static DataProcess.Mathematics.NumberCase;
namespace DataProcess
{
    /// <summary>
    /// 批量处理
    /// </summary>
    namespace Range
    {
        /// <summary>
        ///  关于range类的一些数学基础运用
        /// </summary>
        public class BaseMathTool
        {
            #region 数组准备函数
            /// <summary>
            /// 
            /// </summary>
            /// <param name="max"></param>
            /// <param name="from"></param>
            /// <returns></returns>
            private static int[] getArray(int max, int from)
            {
                List<int> list = new List<int>();
                for (int i = from; i < max; i++)
                {
                    list.Add(i);
                }

                return list.ToArray();
            }
            #endregion
            #region 公倍数
            /// <summary>
            /// 最小公倍数å
            /// </summary>
            /// <param name="nums"></param>
            /// <returns></returns>
            public int MinPublicMulti(params int[] nums)
            {
                int muti = 1;
                foreach (int i in nums)
                {
                    muti *= i;
                }
                if (nums.Length == 2)
                {
                    return muti / MaxpublicSeed(nums);
                }
                else
                {
                    Range<int> mutiPublic = new Range<int>(delegate (int data, int key)
                    {
                        return data % key == 0;
                    }, ConditionLevel.All);
                    int[] p = mutiPublic.Run(getArray(muti, getMax(nums)), nums);
                    if (p.Length > 0)
                    {
                        return p[0];
                    }
                    else
                    {
                        return muti;
                    }
                }
            }

            #endregion
            #region 公因数
            /// <summary>
            /// 最大公因数
            /// </summary>
            /// <param name="nums"></param>
            /// <returns></returns>
            public int MaxpublicSeed(params int[] nums)
            {
                Range<int> publicSeed = new Range<int>(delegate (int data, int key)
                {
                    return key % data == 0;

                }, ConditionLevel.All);
                List<int> list = new List<int>();
                int[] p = publicSeed.Run(getArray(getMin(nums), 2), nums);
                if (p.Length > 0)
                {
                    return p[p.Length - 1];
                }
                else
                {
                    return 1;
                }
            }
            #endregion
            #region 最大最小值
            /// <summary>
            /// 最小值
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            public static int getMin(int[] arr)
            {
                int min = arr[0];
                foreach (int i in arr)
                {
                    if (min > i)
                    {
                        min = i;
                    }
                }
                return min;
            }
            /// <summary>
            /// 最大值
            /// </summary>
            /// <param name="arr"></param>
            /// <returns></returns>
            public static int getMax(int[] arr)
            {
                int max = arr[0];
                foreach (int i in arr)
                {
                    if (max < i)
                    {
                        max = i;
                    }
                }
                return max;
            }
            #endregion
            /// <summary>
            /// 是否为质数
            /// </summary>
            /// <param name="a"></param>
            /// <returns></returns>
            public bool isPrimary(int a)
            {
                if (a < 10)
                {
                    return a == 1 || a == 2 || a == 3 || a == 5 || a == 7;
                }
                else
                {
                    Range<int> isprimary = new Range<int>(delegate (int data, int key)
                    {
                        return data % key == 0;
                    }, ConditionLevel.None);

                    int[] res = isprimary.Run(new int[] { a }, new int[] { 2, 3, 5, 7 });
                    if (res.Length == 0 || res == null)
                    {
                        return false;
                    }
                    else if (res.Length == 1)
                    {
                        return true;
                    }
                    else
                    {
                        throw new Exception("fail");
                    }
                }

            }
        }
        /// <summary>
        /// 条件符合等级
        /// </summary>
        public enum ConditionLevel
        {
            All, Part, None, AllorPart
        }
        /// <summary>
        /// 范围循环类
        /// </summary>
        /// <typeparam name="T">进行循环处理的数据类型</typeparam>
        public class Range<T>
        {
            /// <summary>
            /// 判定条件函数
            /// </summary>
            /// <param name="data">数据</param>
            /// <param name="key">关键值</param>
            /// <returns></returns>
            public delegate bool Condition(T data, T key);
            /// <summary>
            /// 条件匹配函数
            /// </summary>
            public Condition ComputeCondition
            {
                get;
                set;
            }
            /// <summary>
            /// 当前的条件匹配等级
            /// </summary>
            public ConditionLevel ApplyLevel
            {
                get;
                set;
            }
            /// <summary>
            /// 根据数据和关键值，进行条件处理，得到条件匹配等级
            /// </summary>
            /// <param name="data">数据</param>
            /// <param name="keys">关键值</param>
            /// <param name="condition">条件匹配函数</param>
            /// <returns></returns>
            protected static ConditionLevel GetConditionLevel(T data, T[] keys, Condition condition)
            {
                int tnum = 0;
                foreach (T i in keys)
                {
                    if (condition(data, i))
                    {
                        tnum++;
                    }
                }
                return getLevel(tnum, keys.Length);
            }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="condition">条件匹配的方法</param>
            /// <param name="level">能通过的条件匹配等级</param>
            public Range(Condition condition, ConditionLevel level)
            {
                ComputeCondition = condition;
                ApplyLevel = level;
            }
            public Range()
            {
            }
            private static ConditionLevel getLevel(int tnum, int all)
            {
                if (tnum == 0)
                {
                    return ConditionLevel.None;
                }
                else if (tnum < all && tnum > 0)
                {
                    return ConditionLevel.Part;
                }
                else if (tnum == all)
                {
                    return ConditionLevel.All;
                }
                else
                {
                    throw new Exception("获取条件符合级别出错");
                }
            }
            /// <summary>
            /// 基础函数
            /// </summary>
            /// <param name="data"></param>
            /// <param name="keys"></param>
            /// <param name="condition"></param>
            /// <param name="needLevel"></param>
            /// <returns></returns>
            protected virtual T[] baseFuntion(T[] data, T[] keys, Condition condition, ConditionLevel needLevel = ConditionLevel.All)
            {
                List<T> list = new List<T>();
                foreach (T i in data)
                {
                    ConditionLevel keylevel = GetConditionLevel(i, keys, condition);
                    bool isadd = false;
                    if (needLevel == ConditionLevel.AllorPart)
                    {

                        isadd = keylevel != ConditionLevel.None;
                    }
                    else
                    {
                        isadd = keylevel == needLevel;
                    }
                    if (isadd)
                    {
                        list.Add(i);
                    }
                }
                return list.ToArray();
            }
            public T[] Run(T[] data, T[] keys)
            {
                if (ComputeCondition == null)
                {
                    throw new Exception("缺少必要运行条件");
                }

                return Run(data, keys, ComputeCondition, ApplyLevel);
            }
            /// <summary>
            /// 提取数据委托
            /// </summary>
            /// <typeparam name="T1">输入数据类型</typeparam>
            /// <typeparam name="T2">输出数据类型</typeparam>
            /// <param name="now">当前输入数据</param>
            /// <returns>选取出的数据</returns>
            public delegate T2 PickData<T1, T2>(T1 now);
            public static double StandardDeviation(int[] data)
            {
                return StandardDeviation(data, delegate (int n)
                {
                    return n;
                });
            }
            /// <summary>
            /// 平均值
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="pick">选取数据方法</param>
            /// <param name="arr">数据源</param>
            /// <param name="numbers">提取出来的数据</param>
            /// <returns></returns>
            public static double Average<T>(PickData<T, double> pick, T[] arr, out double[] numbers)
            {
                double pj = 0;
                numbers = new double[arr.Length];
                for (int i = 0; i < arr.Length; i++)
                {
                    numbers[i] = pick(arr[i]);
                    pj += numbers[i];
                }
                pj /= arr.Length;
                return pj;
            }

            /// <summary>
            /// 标准差
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="arr">数据源</param>
            /// <param name="pick">选取数据方法</param>
            /// <returns></returns>
            public static double StandardDeviation<T>(T[] arr, PickData<T, double> pick)
            {
                double[] numbers = null;
                double pj = Average(pick, arr, out numbers);
                double t = 0;
                foreach (var i in numbers)
                {
                    t += (i - pj) * (i - pj);
                }
                return Math.Sqrt(t / arr.Length);
            }
            /// <summary>
            /// 运行循环条件筛选
            /// </summary>
            /// <param name="data">需要筛选的数据</param>
            /// <param name="keys">关键值数组，对筛选的数据进行比较或处理</param>
            /// <param name="condition">筛选条件</param>
            /// <param name="level">条件符合等级</param>
            /// <returns></returns>
            public T[] Run(T[] data, T[] keys, Condition condition, ConditionLevel level)
            {
                ComputeCondition = condition;
                ApplyLevel = level;
                return baseFuntion(data, keys, ComputeCondition, ApplyLevel);
            }
        }

        /// <summary>
        /// 模二运算
        /// </summary>
        public class Mod2Math
        {
            /// <summary>
            /// 模二取余
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Mod(string a, string b)
            {
                return Mod2Mod((int)ExchangeToTen(a, 2), (int)ExchangeToTen(b, 2));
            }
            /// <summary>
            /// 模二取余
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Mod(int a, int b)
            {
                string text = ExchangeFromTen(a, 2);
                string text2 = ExchangeFromTen(b, 2);
                int num = text.Length - text2.Length;
                string text3 = "";
                while (num >= 0)
                {
                    int length = text.Length;
                    int num2 = (int)ExchangeToTen(text2, 2) << num;
                    if (text.ToCharArray()[0] == '1')
                    {
                        text = ExchangeFromTen((int)ExchangeToTen(text, 2) ^ num2, 2).PadLeft(length, '0').Substring(1, length - 1);
                        text3 += 1.ToString();
                    }
                    else
                    {
                        text = text.Substring(1, length - 1);
                        text3 += 0.ToString();
                    }

                    num--;
                }

                if (text3.Length >= 1)
                {
                    if (text3[text3.Length - 1].Equals("1"))
                    {
                        return (int)ExchangeToTen(text, 2) ^ b;
                    }
                    if (text.Length == 0)
                    {
                        return 0;
                    }
                    else
                    {
                        return (int)ExchangeToTen(text, 2);
                    }
                }

                return (int)ExchangeToTen(text, 2);
            }
            /// <summary>
            /// 模二除法
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Div(string a, string b)
            {
                return Mod2Div((int)ExchangeToTen(a, 2), (int)ExchangeToTen(b, 2));
            }
            /// <summary>
            /// 模二除法
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Div(int a, int b)
            {
                string a2 = ExchangeFromTen(a, 2);
                string b2 = ExchangeFromTen(b, 2);
                int orginlengh = a2.Length - b2.Length;
                string s = "";
                int tb = b;
                while (orginlengh >= 0)
                {
                    int last = a2.Length;
                    int tmpb = (int)ExchangeToTen(b2, 2) << orginlengh;
                    if (a2.ToCharArray()[0] == '1')
                    {
                        int tpa = (int)ExchangeToTen(a2, 2) ^ tmpb;
                        a2 = ExchangeFromTen(tpa, 2).PadLeft(last, '0').Substring(1, last - 1);
                        s += 1;

                    }
                    else
                    {
                        a2 = a2.Substring(1, last - 1);
                        s += 0;
                    }
                    orginlengh--;
                }
                return (int)ExchangeToTen(s, 2);
            }
            /// <summary>
            /// 模二乘法
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Multy(string a, string b)
            {
                return Mod2Multy((int)ExchangeToTen(a, 2), (int)ExchangeToTen(b, 2));
            }
            /// <summary>
            /// 模二乘法
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static int Mod2Multy(int a, int b)
            {
                string a1 = ExchangeFromTen(a, 2);
                char[] arr = a1.ToCharArray();
                List<int> reslist = new List<int>();
                for (int i = a1.Length - 1; i >= 0; i--)
                {
                    string b1 = ExchangeFromTen(b, 2);
                    if (arr[i] == '1')
                    {
                        reslist.Add(b);
                    }
                    else
                    {
                        reslist.Add(0);
                    }

                    b = b << 1;
                }
                if (reslist.Count >= 1)
                {
                    int t = reslist[0];
                    for (int i = 1; i < reslist.Count; i++)
                    {
                        t ^= reslist[i];
                    }

                    return t;
                }
                else
                {
                    return 0;
                }
            }
        }


    }
}
